/*ticketclerk.c*/
#include "cineplex.h"

void TicketClerk_Scheduler(int index)
{
	agentsStarted = agentsStarted + 1;
	Wait(initCond, initLock);
	tixClerks[index].runScheduler = runSchedulers;
	do
	{
		Acquire(tixClerks[index].msgLock);
		if(tixClerks[index].status==TALKINGTOMANAGER)
		{
			/*if(msgList->Find("Okay"))*/
			TicketClerk_GetMessage(index, Okay);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_ContinueOn(index);
				Release(tixClerks[index].msgLock);
				continue;
			}
			
			/*else if(msgList->Find("GoOnBreak"))*/
			TicketClerk_GetMessage(index, GoOnBreak);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_GoOnBreak(index);
				Release(tixClerks[index].msgLock);
				continue;
			}
			/*else if(msgList->Find("ComeOffBreak"))*/
			TicketClerk_GetMessage(index, ComeOffBreak);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_ComeOffBreak(index);
				Release(tixClerks[index].msgLock);
				continue;
			}
		}
		else if(tixClerks[index].status==WAITINGFORCUST)
		{
			/*I need to use the arguments, so I store the iterList*/
			/*msg=msgList->Find("OrderTix");*/
			TicketClerk_GetMessage(index, OrderTix);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_AskForPayment(index, tixClerks[index].tempMsg.sender);
				Release(tixClerks[index].msgLock);
				continue;
			}
		}
		else if(tixClerks[index].status==WAITINGFORPAY)
		{
			/*msg=msgList->Find("HereIsTixMoney");*/
			TicketClerk_GetMessage(index, HereIsTixMoney);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				/*moneyCollected += msg->GetFloat(1);*/
				tixClerks[index].moneyCollected = tixClerks[index].moneyCollected + (groupSizes[customers[tixClerks[index].tempMsg.sender].groupNumber] * tixClerks[index].TICKET_PRICE);
				TicketClerk_GiveTickets(index, tixClerks[index].tempMsg.sender);
				Release(tixClerks[index].msgLock);
				continue;
			}
		}
		else if(tixClerks[index].status==ONBREAK)
		{
/*			msg=msgList->Find("WhatIsStatus");*/
			TicketClerk_GetMessage(index, WhatIsStatus);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_TellStatus(index);
				Release(tixClerks[index].msgLock);
				continue;
			}
			/*msg=msgList->Find("GiveMeMoney");*/
			TicketClerk_GetMessage(index, GiveMeMoney);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_GiveManagerMoney(index);
				Release(tixClerks[index].msgLock);
				continue;
			}
		}
		else if(tixClerks[index].status==IDLE)
		{
			/*msg=msgList->Find("WhatIsStatus");*/
			TicketClerk_GetMessage(index, WhatIsStatus);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_TellStatus(index);
				Release(tixClerks[index].msgLock);
				continue;
			}
			/*msg=msgList->Find("GiveMeMoney");*/
			TicketClerk_GetMessage(index, GiveMeMoney);
			if(tixClerks[index].tempMsg.sender > -1)
			{
				TicketClerk_GiveManagerMoney(index);
				Release(tixClerks[index].msgLock);
				continue;
			}
			else if(TicketClerk_CallNextInLine(index))
			{
				Release(tixClerks[index].msgLock);
				continue;
			}
		}
		Wait(tixClerks[index].sleepCon, tixClerks[index].msgLock);
	} while(tixClerks[index].runScheduler);
}

struct Message TicketClerk_GetMessage(int index, int name)
{
	/*this will be the null output*/
	tixClerks[index].tempMsg.name = NullMsg;
	tixClerks[index].tempMsg.sender = NullMsg;
	
	Acquire(loopLock);
	for(i = 0; i < tixClerks[index].numMsgs; i++)
	{
		if(tixClerks[index].msgList[i].name == name)
		{
			tixClerks[index].tempMsg.name = name;
			tixClerks[index].tempMsg.sender = tixClerks[index].msgList[i].sender;
			tixClerks[index].numMsgs = tixClerks[index].numMsgs - 1;
			break;
		}
	}
	for(k = i; k < 2; k++)
	{
		/*movin on up*/
		tixClerks[index].msgList[k].name = tixClerks[index].msgList[k+1].name;
		tixClerks[index].msgList[k].sender = tixClerks[index].msgList[k+1].sender;
	}
	tixClerks[index].msgList[2].name = NullMsg;
	tixClerks[index].msgList[2].sender = NullMsg;
	Release(loopLock);
		
	return tixClerks[index].tempMsg;
}

int TicketClerk_CallNextInLine(int index)
{
	Acquire(tixLinesLock);
	tixClerks[index].replyTo = tixLines[index].customers[0];
	if(tixClerks[index].replyTo != -1)
	{	
		/*printf("TicketClerk %s has a line length %i\n", myName, myLine->getSize()+1);*/
		/*cust->SendMessage("ComeBuyTix",1,this);*/
		ConsoleAcquire();
			Write("TicketClerk ", 12, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" has a line length ", 19, ConsoleOutput);
			outputLen = Itoa(Line_getSize(T_TICKETCLERK,index), outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write("\n", 1, ConsoleOutput);
		ConsoleRelease();
		customers[index].state = WAITTIXLINE;
		SendMessage(T_CUSTOMER, tixClerks[index].replyTo, ComeBuyTix, index);
		Release(tixLinesLock);
		tixClerks[index].status=WAITINGFORCUST;
		return 1;
	}
	Release(tixLinesLock);
	/*printf("TicketClerk %s has no one in line.  I am available for a customer\n", myName);*/
	ConsoleAcquire();
		Write("TicketClerk ", 12, ConsoleOutput);
		outputLen = Itoa(index, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" has no one in line.  I am available for a customer\n", 52, ConsoleOutput);
	ConsoleRelease();
	return 0;
}

void TicketClerk_AskForPayment(int index, int cust)
{
	/*money=TICKET_PRICE*size;*/ /*MBC*/
	/*printf("TicketClerk %s has an order for %i and the cost is %.2f\n", myName,size,money);*/
	ConsoleAcquire();
	Write("TicketClerk ", 12, ConsoleOutput);
	outputLen = Itoa(index, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" has an order for ", 18, ConsoleOutput);
	outputLen = Itoa(groupSizes[groupNums[cust]], outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" and the cost is $", 18, ConsoleOutput);
	outputLen = Itoa(groupSizes[groupNums[cust]]*tixClerks[index].TICKET_PRICE, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write("\n", 1, ConsoleOutput);
	ConsoleRelease();
	/*cust->SendMessage("PayMeForTix",2,this,&money);*/
	SendMessage(T_CUSTOMER, cust, PayMeForTix, index);
	tixClerks[index].status=WAITINGFORPAY;	
}

void TicketClerk_GiveTickets(int index, int cust)
{
	/*MBC*/
	/*cust->SendMessage("HereAreTickets",2,tickets,&groupSize);*/
	SendMessage(T_CUSTOMER, cust, HereAreTickets, index);
	/* *moneyCollected+=payment;*/
	tixClerks[index].status=IDLE;
}

void TicketClerk_GiveManagerMoney(int index)
{
	/*manager->SendMessage("HereIsMoney",2,this,moneyCollected);*/
	SendMessage(T_MANAGER, 0, tixClerks[index].moneyCollected, index);
	/*moneyCollected=0.0f;*/ /*MBM*/
}

void TicketClerk_TellStatus(int index)
{
	if(tixClerks[index].status==ONBREAK)
	{
		tixClerks[index].lineLength=-1;
		tixClerks[index].onBreak=1;
	}
	else
	{
		tixClerks[index].lineLength = tixLines[index].length;
		tixClerks[index].onBreak=0;
	}
	
	/*manager->SendMessage("NumInLine",2,this,&lineLength);*/
	SendMessage(T_MANAGER, 0, NumInLine, index);
	tixClerks[index].status=TALKINGTOMANAGER;
}

void TicketClerk_ContinueOn(int index)
{
	if(tixClerks[index].onBreak)
	{
		tixClerks[index].status=ONBREAK;
	}
	else
	{
		tixClerks[index].status=IDLE;
	}
}

void TicketClerk_GoOnBreak(int index)
{
	/*printf("TicketClerk %s is going on break\n", myName);*/
	tixLines[index].isOpen=0;
	tixLines[index].length = -1;
	tixClerks[index].status=ONBREAK;
}

void TicketClerk_ComeOffBreak(int index)
{
	/*printf("TicketClerk %s is coming off break\n", myName);*/
	tixLines[index].isOpen=1;
	tixLines[index].length=0;
	tixClerks[index].status=IDLE;
}
